package com.edu.exam.entity.grading.audit;

import com.edu.exam.enums.grading.AuditNodePriority;
import com.edu.exam.enums.grading.AuditNodeStatus;
import com.edu.exam.enums.grading.AuditNodeType;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

/**
 * 成绩审核节点实体类
 *
 * <p>成绩审核节点实体用于管理工作流中的具体审核节点，包含
 * 节点配置信息、处理者信息、执行状态、动作管理等。支持复杂的审核流程控制和节点协作。</p>
 *
 * <p>所属模块：B-06 成绩管理模块</p>
 * <p>对应数据库表：grade_audit_node</p>
 *
 * <p>核心功能：
 * - 节点配置：管理节点的基本配置和属性
 * - 处理者管理：管理节点的处理者和权限
 * - 状态控制：管理节点的执行状态和生命周期
 * - 动作管理：管理节点中可执行的审核动作
 * - 执行监控：监控节点的执行过程和结果</p>
 *
 * @author 系统生成
 * @version 2.0
 * @since 2025-11-15
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
public class GradeAuditNode {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 工作流ID
     *
     * <p>所属工作流的ID。</p>
     */
    @Column(name = "workflow_id", nullable = false, length = 50)
    private String workflowId;

    /**
     * 节点ID
     *
     * <p>节点的唯一标识符。</p>
     */
    @Column(name = "node_id", nullable = false, length = 50, unique = true)
    private String nodeId;

    /**
     * 节点名称
     *
     * <p>节点的显示名称。</p>
     */
    @Column(name = "node_name", nullable = false, length = 200)
    private String nodeName;

    /**
     * 节点类型
     *
     * <p>节点的类型。
     * 支持的类型：START（开始节点）、END（结束节点）、APPROVAL（审核节点）、NOTIFICATION（通知节点）、CONDITION（条件节点）、PARALLEL（并行节点）、MERGE（合并节点）、SERVICE（服务节点）</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "node_type", nullable = false, length = 20)
    private AuditNodeType nodeType = AuditNodeType.APPROVAL;

    /**
     * 节点状态
     *
     * <p>节点的执行状态。
     * 支持的状态：INACTIVE（未激活）、ACTIVE（激活）、RUNNING（运行中）、COMPLETED（已完成）、FAILED（失败）、SKIPPED（已跳过）、CANCELLED（已取消）</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "node_status", nullable = false, length = 20)
    private AuditNodeStatus nodeStatus = AuditNodeStatus.INACTIVE;

    /**
     * 节点优先级
     *
     * <p>节点的执行优先级。
     * 支持的优先级：LOW（低优先级）、NORMAL（普通优先级）、HIGH（高优先级）、URGENT（紧急）、CRITICAL（关键）</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "node_priority", nullable = false, length = 20)
    private AuditNodePriority nodePriority = AuditNodePriority.NORMAL;

    /**
     * 节点描述
     *
     * <p>节点的详细描述。</p>
     */
    @Column(name = "description", columnDefinition = "TEXT")
    private String description;

    /**
     * 父节点ID
     *
     * <p>父节点的ID，用于构建节点层级关系。</p>
     */
    @Column(name = "parent_node_id", length = 50)
    private String parentNodeId;

    /**
     * 序列号
     *
     * <p>节点在工作流中的执行顺序。</p>
     */
    @Column(name = "sequence_number")
    private Integer sequenceNumber;

    /**
     * 并行组ID
     *
     * <p>并行节点的组ID，用于识别同一并行组内的节点。</p>
     */
    @Column(name = "parallel_group_id", length = 50)
    private String parallelGroupId;

    /**
     * 是否必经节点
     *
     * <p>标记是否为必须执行的节点。</p>
     */
    @Column(name = "is_required", nullable = false)
    private Boolean isRequired = true;

    /**
     * 是否允许跳过
     *
     * <p>标记是否允许跳过该节点。</p>
     */
    @Column(name = "allow_skip", nullable = false)
    private Boolean allowSkip = false;

    /**
     * 是否支持并行
     *
     * <p>标记是否支持并行执行。</p>
     */
    @Column(name = "support_parallel", nullable = false)
    private Boolean supportParallel = false;

    /**
     * 处理者类型
     *
     * <p>节点处理者的类型：USER（指定用户）、ROLE（指定角色）、DEPARTMENT（指定部门）、SYSTEM（系统自动处理）</p>
     */
    @Column(name = "assignee_type", length = 20)
    private String assigneeType;

    /**
     * 处理者ID
     *
     * <p>节点处理者的ID。</p>
     */
    @Column(name = "assignee_id", length = 100)
    private String assigneeId;

    /**
     * 处理者名称
     *
     * <p>节点处理者的名称。</p>
     */
    @Column(name = "assignee_name", length = 200)
    private String assigneeName;

    /**
     * 执行超时时间（分钟）
     *
     * <p>节点执行的超时时间，单位为分钟。</p>
     */
    @Column(name = "timeout_minutes")
    private Integer timeoutMinutes;

    /**
     * 执行条件
     *
     * <p>节点执行的条件，JSON格式存储。</p>
     */
    @Column(name = "execution_condition", columnDefinition = "TEXT")
    private String executionCondition;

    /**
     * 执行参数
     *
     * <p>节点执行所需的参数，JSON格式存储。</p>
     */
    @Column(name = "execution_parameters", columnDefinition = "TEXT")
    private String executionParameters;

    /**
     * 执行结果
     *
     * <p>节点执行的结果数据。</p>
     */
    @Column(name = "execution_result", columnDefinition = "TEXT")
    private String executionResult;

    /**
     * 执行开始时间
     *
     * <p>节点开始执行的时间。</p>
     */
    @Column(name = "execution_start_time")
    private LocalDateTime executionStartTime;

    /**
     * 执行结束时间
     *
     * <p>节点结束执行的时间。</p>
     */
    @Column(name = "execution_end_time")
    private LocalDateTime executionEndTime;

    /**
     * 执行时长（毫秒）
     *
     * <p>节点执行所花费的时间，单位为毫秒。</p>
     */
    @Column(name = "execution_duration_ms")
    private Long executionDurationMs;

    /**
     * 重试次数
     *
     * <p>节点执行失败后的重试次数。</p>
     */
    @Column(name = "retry_count")
    private Integer retryCount = 0;

    /**
     * 最大重试次数
     *
     * <p>节点允许的最大重试次数。</p>
     */
    @Column(name = "max_retry_count")
    private Integer maxRetryCount = 3;

    /**
     * 执行日志
     *
     * <p>节点执行过程的日志记录。</p>
     */
    @Column(name = "execution_log", columnDefinition = "TEXT")
    private String executionLog;

    /**
     * 错误信息
     *
     * <p>节点执行失败时的错误信息。</p>
     */
    @Column(name = "error_message", columnDefinition = "TEXT")
    private String errorMessage;

    /**
     * 节点配置
     *
     * <p>节点的配置信息，JSON格式存储。</p>
     */
    @Column(name = "node_configuration", columnDefinition = "TEXT")
    private String nodeConfiguration;

    /**
     * 节点标签
     *
     * <p>节点的分类标签，用于节点分组和过滤。</p>
     */
    @Column(name = "node_tags", length = 500)
    private String nodeTags;

    /**
     * 前置节点ID列表
     *
     * <p>该节点的前置节点ID列表，用逗号分隔。</p>
     */
    @Column(name = "predecessor_nodes", length = 500)
    private String predecessorNodes;

    /**
     * 后置节点ID列表
     *
     * <p>该节点的后置节点ID列表，用逗号分隔。</p>
     */
    @Column(name = "successor_nodes", length = 500)
    private String successorNodes;

    /**
     * 依赖节点ID列表
     *
     * <p>该节点依赖的其他节点ID列表，用逗号分隔。</p>
     */
    @Column(name = "dependency_nodes", length = 500)
    private String dependencyNodes;

    /**
     * 排除节点ID列表
     *
     * <p>需要排除的节点ID列表，用逗号分隔。</p>
     */
    @Column(name = "exclusion_nodes", length = 500)
    private String exclusionNodes;

    /**
     * 节点图标
     *
     * <p>节点在流程图中的图标标识。</p>
     */
    @Column(name = "node_icon", length = 50)
    private String nodeIcon;

    /**
     * 节点颜色
     *
     * <p>节点在流程图中的显示颜色。</p>
     */
    @Column(name = "node_color", length = 7)
    private String nodeColor;

    /**
     * 节点位置X
     *
     * <p>节点在流程图中的X坐标位置。</p>
     */
    @Column(name = "position_x")
    private Double positionX;

    /**
     * 节点位置Y
     *
     * <p>节点在流程图中的Y坐标位置。</p>
     */
    @Column(name = "position_y")
    private Double positionY;

    /**
     * 节点宽度
     *
     * <p>节点在流程图中的显示宽度。</p>
     */
    @Column(name = "node_width")
    private Double nodeWidth;

    /**
     * 节点高度
     *
     * <p>节点在流程图中的显示高度。</p>
     */
    @Column(name = "node_height")
    private Double nodeHeight;

    /**
     * 是否显示
     *
     * <p>标记是否在流程图中显示该节点。</p>
     */
    @Column(name = "is_visible", nullable = false)
    private Boolean isVisible = true;

    /**
     * 是否折叠
     *
     * <p>标记是否折叠显示该节点。</p>
     */
    @Column(name = "is_collapsed", nullable = false)
    private Boolean isCollapsed = false;

    /**
     * 节点备注
     *
     * <p>节点的备注信息。</p>
     */
    @Column(name = "node_notes", columnDefinition = "TEXT")
    private String nodeNotes;

    /**
     * 创建者ID
     *
     * <p>创建节点的用户ID。</p>
     */
    @Column(name = "creator_id")
    private Long creatorId;

    /**
     * 创建者姓名
     *
     * <p>创建节点的用户姓名。</p>
     */
    @Column(name = "creator_name", length = 100)
    private String creatorName;

    // ===== 审计字段 =====

    /**
     * 创建时间
     */
    @CreatedDate
    @Column(name = "create_time", nullable = false, updatable = false)
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    @LastModifiedDate
    @Column(name = "update_time", nullable = false)
    private LocalDateTime updateTime;

    /**
     * 创建人ID
     */
    @Column(name = "created_by")
    private Long createdBy;

    /**
     * 更新人ID
     */
    @Column(name = "updated_by")
    private Long updatedBy;

    /**
     * 版本号（乐观锁）
     */
    @Version
    @Column(name = "version")
    private Long version;

    /**
     * 逻辑删除标记
     */
    @Column(name = "is_deleted", nullable = false)
    private Boolean isDeleted = false;
}